<template>
  <el-dialog
    title="上传素材"
    :visible="visible"
    width="400px"
    :before-close="handleClose"
  >
    <el-upload
      class="upload-demo"
      drag
      multiple
      action="#"
      :disabled="!!uploadFile"
      :auto-upload="false"
      :file-list="fileList"
      :limit="1"
      accept=".mp4"
      :on-change="changeFile"
    >
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
      <div style="text-align: center" class="el-upload__tip" slot="tip">
        仅支持上传.mp4格式的视频
      </div>
    </el-upload>
    <video id="videoPlayer" style="display: none"></video>
    <el-progress v-if="showProgress" :percentage="progress"></el-progress>
    <div slot="footer">
      <el-button @click="handleClose">取消</el-button>
      <el-button type="primary" @click="handleConfirm">上传</el-button>
    </div>
  </el-dialog>
</template>

<script>
import { AddResource, CompleteUpload } from "@/api/course/material.js";
import OSS from "ali-oss";
const client = new OSS({
  region: "oss-cn-guangzhou",
  accessKeyId: "LTAI5tJUD5TjobLAhwP7EgoY",
  accessKeySecret: "5pkpK8Brl8SpBePwxcEw1tn3pBbxzp",
  stsToken: "",
  bucket: "qinxue18984155632",
});
export default {
  name: "AddSourceChunk",
  data() {
    return {
      visible: false,
      fileList: [],
      uploadFile: null,
      progress: 0,
      partInfos: [],
      uploadId: "",
      showProgress: false,
    };
  },
  methods: {
    async uploadPart(file, uploadId, partNumber, start, end) {
      const chunk = file.raw.slice(start, end); // 获取分片数据
      try {
        const result = await client.uploadPart(
          file.name,
          uploadId,
          partNumber,
          chunk
        );
        this.partInfos.push({
          partNumber: partNumber,
          eTag: result.etag,
        });
      } catch (err) {
        console.log(err);
      }
    },
    async resumeUpload(file) {
      const chunkSize = 5 * 1024 * 1024; // 分片大小，5MB
      const totalChunks = Math.ceil(file.size / chunkSize); // 总分片数
      this.progress = 0;
      this.uploadId = "";
      this.showProgress = true;

      // 1. 初始化分片上传
      if (!this.uploadId) {
        const initResult = await client.initMultipartUpload(file.name);
        this.uploadId = initResult.uploadId;
      }
      // 2. 上传分片
      for (let i = this.partInfos.length; i < totalChunks; i++) {
        const start = i * chunkSize;
        const end = Math.min(start + chunkSize, file.size);

        try {
          await this.uploadPart(file, this.uploadId, i + 1, start, end);
          this.progress =
            this.progress === 100
              ? 99
              : parseInt(((i + 1) / totalChunks) * 100);
          console.log(`分片 ${i + 1} 上传成功`);
        } catch (error) {
          console.error(`分片 ${i + 1} 上传失败:`, error);
          return;
        }
      }
      const params = {
        fileName: file.name,
        uploadId: this.uploadId,
        partETags: this.partInfos.sort((a, b) => a.partNumber - b.partNumber),
      };
      try {
        const res = await CompleteUpload(params);
        if (res.code === 200) {
          this.uploadResource({
            name: file.name,
            url: res.data,
            size: file.size,
            videoLength: file.duration,
          });
        } else {
          this.$message.error("上传失败");
          this.showProgress = false;
        }
      } catch (error) {
        this.showProgress = false;
      }
    },
    async handleConfirm() {
      if (!this.uploadFile) {
        this.$message.error("请选择文件");
        return;
      }
      const res = await AddResource({
        resourceName: this.uploadFile.name,
        resourceType: 1,
      });
      if (res.code === 200) {
        this.resumeUpload({ ...this.uploadFile });
      }
    },
    show() {
      this.visible = true;
    },
    changeFile(file) {
      if (!["mp4"].includes(file.name.split(".").pop())) {
        this.$message.error(`仅支持上传.mp4格式的图片文件`);
        this.fileList = [];
        return;
      }
      if (file.size > 1500 * 1024 * 1024) {
        this.$message.error(`文件大小不能超过1500MB`);
        this.fileList = [];
        return;
      }
      this.uploadFile = file;
      const video = document.getElementById("videoPlayer");
      const url = URL.createObjectURL(file.raw);
      video.src = url;
      video.onloadedmetadata = () => {
        // 等待元数据加载完成
        this.uploadFile.duration = video.duration;
        URL.revokeObjectURL(url);
      };
    },
    handleConfirm() {
      if (!this.uploadFile) {
        this.$message.error("请选择文件");
        return;
      }
      this.resumeUpload(this.uploadFile);
    },
    handleClose() {
      if (this.showProgress) {
        this.$confirm("视频正在上传，确定要关闭吗？", "提示").then(() => {
          this.uploadId = "";
          this.uploadFile = null;
          this.showProgress = false;
          this.progress = 0;
          this.partInfos = [];
          this.fileList = [];
          this.visible = false;
        });
      } else {
        this.uploadId = "";
        this.uploadFile = null;
        this.showProgress = false;
        this.progress = 0;
        this.partInfos = [];
        this.fileList = [];
        this.visible = false;
      }
    },
    uploadResource(data) {
      const params = {
        resourceName: data.name,
        resourceUrl: data.url,
        resourceSize: data.size,
        resourceType: 1,
        videoLength: data.videoLength,
      };
      AddResource(params)
        .then((res) => {
          if (res.code === 200) {
            this.showProgress = false;
            this.$message.success("上传成功");
            this.$emit("refresh");
            this.handleClose();
          }
        })
        .finally(() => {
          this.showProgress = false;
        });
    },
  },
};
</script>

<style scoped>
.uploader-example {
  width: 100%;
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
  font-size: 12px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
</style>